home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 with MFC / Programming Windows 95 with MFC (Microsoft Programming Series)(097-0001465)(1996).iso / CODE / Chap07 / Clock / Clock.cpp next >
Encoding:
C/C++ Source or Header  |  1996-04-05  |  13.7 KB  |  483 lines

  1. //***********************************************************************
  2. //
  3. //  Clock.cpp
  4. //
  5. //***********************************************************************
  6.  
  7. #include <afxwin.h>
  8. #include <math.h>
  9. #include "Resource.h"
  10. #include "Clock.h"
  11.  
  12. #define SQUARESIZE 20
  13.  
  14. CMyApp myApp;
  15.  
  16. /////////////////////////////////////////////////////////////////////////
  17. // CMyApp member functions
  18.  
  19. BOOL CMyApp::InitInstance ()
  20. {
  21.     SetRegistryKey ("Programming Windows 95 with MFC");
  22.  
  23.     m_pMainWnd = new CMainWindow;
  24.  
  25.     if (!((CMainWindow*) m_pMainWnd)->RestoreWindowState ())
  26.         m_pMainWnd->ShowWindow (m_nCmdShow);
  27.  
  28.     m_pMainWnd->UpdateWindow ();
  29.     return TRUE;
  30. }
  31.  
  32. /////////////////////////////////////////////////////////////////////////
  33. // CMainWindow message map and member functions
  34.  
  35. BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
  36.     ON_WM_CREATE ()
  37.     ON_WM_PAINT ()
  38.     ON_WM_TIMER ()
  39.     ON_WM_GETMINMAXINFO ()
  40.     ON_WM_NCHITTEST ()
  41.     ON_WM_SYSCOMMAND ()
  42.     ON_WM_CONTEXTMENU ()
  43.     ON_WM_ENDSESSION ()
  44.     ON_WM_CLOSE ()
  45. END_MESSAGE_MAP ()
  46.  
  47. CMainWindow::CMainWindow ()
  48. {
  49.     m_bAutoMenuEnable = FALSE;
  50.  
  51.     CTime time = CTime::GetCurrentTime ();
  52.     m_nPrevSecond = time.GetSecond ();
  53.     m_nPrevMinute = time.GetMinute ();
  54.     m_nPrevHour = time.GetHour () % 12;
  55.  
  56.     CString strWndClass = AfxRegisterWndClass (
  57.         CS_HREDRAW | CS_VREDRAW,
  58.         myApp.LoadStandardCursor (IDC_ARROW),
  59.         (HBRUSH) (COLOR_3DFACE + 1),
  60.         myApp.LoadIcon (IDI_APPICON)
  61.     );
  62.  
  63.     Create (strWndClass, "Clock");
  64. }
  65.  
  66. BOOL CMainWindow::PreCreateWindow (CREATESTRUCT& cs)
  67. {
  68.     if (!CFrameWnd::PreCreateWindow (cs))
  69.         return FALSE;
  70.  
  71.     cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
  72.     return TRUE;
  73. }
  74.  
  75. int CMainWindow::OnCreate (LPCREATESTRUCT lpcs)
  76. {
  77.     if (CFrameWnd::OnCreate (lpcs) == -1)
  78.         return -1;
  79.  
  80.     if (!SetTimer (ID_TIMER_CLOCK, 1000, NULL)) {
  81.         MessageBox ("SetTimer failed", "Error", MB_ICONSTOP | MB_OK);
  82.         return -1;
  83.     }
  84.  
  85.     CMenu* pMenu = GetSystemMenu (FALSE);
  86.     pMenu->AppendMenu (MF_SEPARATOR);
  87.     pMenu->AppendMenu (MF_STRING, IDM_SYSMENU_FULL_WINDOW,
  88.         "Remove &Title");
  89.     pMenu->AppendMenu (MF_STRING, IDM_SYSMENU_STAY_ON_TOP,
  90.         "Stay on To&p");
  91.     pMenu->AppendMenu (MF_SEPARATOR);
  92.     pMenu->AppendMenu (MF_STRING, IDM_SYSMENU_ABOUT,
  93.         "&About Clock...");
  94.     return 0;
  95. }
  96.  
  97. void CMainWindow::OnClose ()
  98. {
  99.     SaveWindowState ();
  100.     KillTimer (ID_TIMER_CLOCK);
  101.     CFrameWnd::OnClose ();
  102. }
  103.  
  104. void CMainWindow::OnEndSession (BOOL bEnding)
  105. {
  106.     if (bEnding)
  107.         SaveWindowState ();
  108.     CFrameWnd::OnEndSession (bEnding);
  109. }
  110.  
  111. void CMainWindow::OnGetMinMaxInfo (MINMAXINFO* pMMI)
  112. {
  113.     pMMI->ptMinTrackSize.x = 120;
  114.     pMMI->ptMinTrackSize.y = 120;
  115. }
  116.  
  117. UINT CMainWindow::OnNcHitTest (CPoint point)
  118. {
  119.     UINT nHitTest = CFrameWnd::OnNcHitTest (point);
  120.     if ((nHitTest == HTCLIENT) && (::GetAsyncKeyState (MK_LBUTTON) < 0))
  121.         nHitTest = HTCAPTION;
  122.     return nHitTest;
  123. }
  124.  
  125. void CMainWindow::OnSysCommand (UINT nID, LPARAM lParam)
  126. {
  127.     UINT nMaskedID = nID & 0xFFF0;
  128.  
  129.     if (nMaskedID == IDM_SYSMENU_FULL_WINDOW) {
  130.         m_bFullWindow = m_bFullWindow ? 0 : 1;
  131.         SetTitleBarState ();
  132.         return;
  133.     }
  134.     else if (nMaskedID == IDM_SYSMENU_STAY_ON_TOP) {
  135.         m_bStayOnTop = m_bStayOnTop ? 0 : 1;
  136.         SetTopMostState ();
  137.         return;
  138.     }
  139.     else if (nMaskedID == IDM_SYSMENU_ABOUT) {
  140.         CAboutDialog dlg (this);
  141.         dlg.DoModal ();
  142.         return;
  143.     }
  144.     CFrameWnd::OnSysCommand (nID, lParam);
  145. }
  146.  
  147. void CMainWindow::OnContextMenu (CWnd* pWnd, CPoint point)
  148. {
  149.     CRect rect;
  150.     GetClientRect (&rect);
  151.     ClientToScreen (&rect);
  152.  
  153.     if (rect.PtInRect (point)) {
  154.         CMenu* pMenu = GetSystemMenu (FALSE);
  155.         UpdateSystemMenu (pMenu);
  156.  
  157.         int nID = (int) pMenu->TrackPopupMenu (TPM_LEFTALIGN |
  158.             TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x,
  159.             point.y, this);
  160.  
  161.         if (nID > 0)
  162.             SendMessage (WM_SYSCOMMAND, nID, 0);
  163.  
  164.         return;
  165.     }
  166.     CFrameWnd::OnContextMenu (pWnd, point);
  167. }
  168.  
  169. void CMainWindow::OnTimer (UINT nTimerID)
  170. {
  171.     if (IsIconic ()) // Don't paint while minimized!
  172.         return;
  173.  
  174.     CTime time = CTime::GetCurrentTime ();
  175.     int nSecond = time.GetSecond ();
  176.     int nMinute = time.GetMinute ();
  177.     int nHour = time.GetHour () % 12;
  178.  
  179.     if ((nSecond == m_nPrevSecond) &&
  180.         (nMinute == m_nPrevMinute) &&
  181.         (nHour == m_nPrevHour))
  182.         return;
  183.  
  184.     CRect rect;
  185.     GetClientRect (&rect);
  186.  
  187.     CClientDC dc (this);
  188.     dc.SetMapMode (MM_ISOTROPIC);
  189.     dc.SetWindowExt (1000, 1000);
  190.     dc.SetViewportExt (rect.Width (), -rect.Height ());
  191.     dc.SetViewportOrg (rect.Width () / 2, rect.Height () / 2);
  192.  
  193.     COLORREF crColor = (COLORREF) GetSysColor (COLOR_3DFACE);
  194.  
  195.     if (nMinute != m_nPrevMinute) {
  196.         DrawHand (&dc, 200, 4, (m_nPrevHour * 30) + (m_nPrevMinute / 2),
  197.             crColor);
  198.         DrawHand (&dc, 400, 8, m_nPrevMinute * 6, crColor);
  199.         m_nPrevMinute = nMinute;
  200.         m_nPrevHour = nHour;
  201.     }
  202.  
  203.     if (nSecond != m_nPrevSecond) {
  204.         DrawSecondHand (&dc, 400, 8, m_nPrevSecond * 6, crColor);
  205.         DrawSecondHand (&dc, 400, 8, nSecond * 6, RGB (0, 0, 0));
  206.         DrawHand (&dc, 200, 4, (nHour * 30) + (nMinute / 2),
  207.             RGB (0, 0, 0));
  208.         DrawHand (&dc, 400, 8, nMinute * 6, RGB (0, 0, 0));
  209.         m_nPrevSecond = nSecond;
  210.     }
  211. }
  212.  
  213. void CMainWindow::OnPaint ()
  214. {
  215.     CRect rect;
  216.     GetClientRect (&rect);
  217.  
  218.     CPaintDC dc (this);
  219.     dc.SetMapMode (MM_ISOTROPIC);
  220.     dc.SetWindowExt (1000, 1000);
  221.     dc.SetViewportExt (rect.Width (), -rect.Height ());
  222.     dc.SetViewportOrg (rect.Width () / 2, rect.Height () / 2);
  223.  
  224.     DrawClockFace (&dc);
  225.     DrawHand (&dc, 200, 4, (m_nPrevHour * 30) +
  226.         (m_nPrevMinute / 2), RGB (0, 0, 0));
  227.     DrawHand (&dc, 400, 8, m_nPrevMinute * 6, RGB (0, 0, 0));
  228.     DrawSecondHand (&dc, 400, 8, m_nPrevSecond * 6, RGB (0, 0, 0));
  229. }
  230.  
  231. void CMainWindow::DrawClockFace (CDC* pDC)
  232. {
  233.     static CPoint point[12] = {
  234.         CPoint (   0,  450),    // 12 o'clock
  235.         CPoint ( 225,  390),    //  1 o'clock
  236.         CPoint ( 390,  225),    //  2 o'clock
  237.         CPoint ( 450,    0),    //  3 o'clock
  238.         CPoint ( 390, -225),    //  4 o'clock
  239.         CPoint ( 225, -390),    //  5 o'clock
  240.         CPoint (   0, -450),    //  6 o'clock
  241.         CPoint (-225, -390),    //  7 o'clock
  242.         CPoint (-390, -225),    //  8 o'clock
  243.         CPoint (-450,    0),    //  9 o'clock
  244.         CPoint (-390,  225),    // 10 o'clock
  245.         CPoint (-225,  390),    // 11 o'clock
  246.     };
  247.  
  248.     pDC->SelectStockObject (NULL_BRUSH);
  249.  
  250.     for (int i=0; i<12; i++)
  251.         pDC->Rectangle (point[i].x - SQUARESIZE,
  252.             point[i].y + SQUARESIZE, point[i].x + SQUARESIZE,
  253.             point[i].y - SQUARESIZE);
  254. }
  255.  
  256. void CMainWindow::DrawHand (CDC* pDC, int nLength, int nScale,
  257.     int nDegrees, COLORREF crColor)
  258. {
  259.     CPoint point[4];
  260.     double nRadians = (double) nDegrees * 0.017453292;
  261.  
  262.     point[0].x = (int) (nLength * sin (nRadians));
  263.     point[0].y = (int) (nLength * cos (nRadians));
  264.  
  265.     point[2].x = -point[0].x / nScale;
  266.     point[2].y = -point[0].y / nScale;
  267.  
  268.     point[1].x = -point[2].y;
  269.     point[1].y = point[2].x;
  270.  
  271.     point[3].x = -point[1].x;
  272.     point[3].y = -point[1].y;
  273.  
  274.     CPen pen (PS_SOLID, 0, crColor);
  275.     CPen* pOldPen = pDC->SelectObject (&pen);
  276.  
  277.     pDC->MoveTo (point[0]);
  278.     pDC->LineTo (point[1]);
  279.     pDC->LineTo (point[2]);
  280.     pDC->LineTo (point[3]);
  281.     pDC->LineTo (point[0]);
  282.  
  283.     pDC->SelectObject (pOldPen);
  284. }
  285.  
  286. void CMainWindow::DrawSecondHand (CDC* pDC, int nLength, int nScale,
  287.     int nDegrees, COLORREF crColor)
  288. {
  289.     CPoint point[2];
  290.     double nRadians = (double) nDegrees * 0.017453292;
  291.  
  292.     point[0].x = (int) (nLength * sin (nRadians));
  293.     point[0].y = (int) (nLength * cos (nRadians));
  294.  
  295.     point[1].x = -point[0].x / nScale;
  296.     point[1].y = -point[0].y / nScale;
  297.  
  298.     CPen pen (PS_SOLID, 0, crColor);
  299.     CPen* pOldPen = pDC->SelectObject (&pen);
  300.  
  301.     pDC->MoveTo (point[0]);
  302.     pDC->LineTo (point[1]);
  303.  
  304.     pDC->SelectObject (pOldPen);
  305. }
  306.  
  307. void CMainWindow::SetTitleBarState ()
  308. {
  309.     CMenu* pMenu = GetSystemMenu (FALSE);
  310.  
  311.     if (m_bFullWindow ) {
  312.         ModifyStyle (WS_CAPTION, 0);
  313.         pMenu->ModifyMenu (IDM_SYSMENU_FULL_WINDOW, MF_STRING,
  314.             IDM_SYSMENU_FULL_WINDOW, "Restore &Title");
  315.     }
  316.     else {
  317.         ModifyStyle (0, WS_CAPTION);
  318.         pMenu->ModifyMenu (IDM_SYSMENU_FULL_WINDOW, MF_STRING,
  319.             IDM_SYSMENU_FULL_WINDOW, "Remove &Title");
  320.     }
  321.  
  322.     SetWindowPos (NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
  323.         SWP_NOZORDER | SWP_DRAWFRAME);
  324. }
  325.  
  326. void CMainWindow::SetTopMostState ()
  327. {
  328.     CMenu* pMenu = GetSystemMenu (FALSE);
  329.  
  330.     if (m_bStayOnTop) {
  331.         SetWindowPos (&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  332.         pMenu->CheckMenuItem (IDM_SYSMENU_STAY_ON_TOP, MF_CHECKED);
  333.     }       
  334.     else {
  335.         SetWindowPos (&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
  336.         pMenu->CheckMenuItem (IDM_SYSMENU_STAY_ON_TOP, MF_UNCHECKED);
  337.     }
  338. }
  339.  
  340. BOOL CMainWindow::RestoreWindowState ()
  341. {
  342.     CString version = "Version 1.0";
  343.  
  344.     m_bFullWindow = myApp.GetProfileInt (version, "FullWindow", 0);
  345.     SetTitleBarState ();
  346.  
  347.     m_bStayOnTop = myApp.GetProfileInt (version, "StayOnTop", 0);
  348.     SetTopMostState ();
  349.  
  350.     WINDOWPLACEMENT wp;
  351.     wp.length = sizeof (WINDOWPLACEMENT);
  352.     GetWindowPlacement (&wp);
  353.  
  354.     if (((wp.flags =
  355.             myApp.GetProfileInt (version, "flags", -1)) != -1) &&
  356.         ((wp.showCmd =
  357.             myApp.GetProfileInt (version, "showCmd", -1)) != -1) &&
  358.         ((wp.rcNormalPosition.left =
  359.             myApp.GetProfileInt (version, "x1", -1)) != -1) &&
  360.         ((wp.rcNormalPosition.top =
  361.             myApp.GetProfileInt (version, "y1", -1)) != -1) &&
  362.         ((wp.rcNormalPosition.right =
  363.             myApp.GetProfileInt (version, "x2", -1)) != -1) &&
  364.         ((wp.rcNormalPosition.bottom =
  365.             myApp.GetProfileInt (version, "y2", -1)) != -1)) {
  366.  
  367.         wp.rcNormalPosition.left = min (wp.rcNormalPosition.left,
  368.             ::GetSystemMetrics (SM_CXSCREEN) -
  369.             ::GetSystemMetrics (SM_CXICON));
  370.         wp.rcNormalPosition.top = min (wp.rcNormalPosition.top,
  371.             ::GetSystemMetrics (SM_CYSCREEN) -
  372.             ::GetSystemMetrics (SM_CYICON));
  373.  
  374.         SetWindowPlacement (&wp);
  375.         return TRUE;
  376.     }
  377.     return FALSE;
  378. }
  379.  
  380. void CMainWindow::SaveWindowState ()
  381. {
  382.     CString version = "Version 1.0";
  383.  
  384.     myApp.WriteProfileInt (version, "FullWindow", m_bFullWindow);
  385.     myApp.WriteProfileInt (version, "StayOnTop", m_bStayOnTop);
  386.  
  387.     WINDOWPLACEMENT wp;
  388.     wp.length = sizeof (WINDOWPLACEMENT);
  389.     GetWindowPlacement (&wp);
  390.  
  391.     myApp.WriteProfileInt (version, "flags", wp.flags);
  392.     myApp.WriteProfileInt (version, "showCmd", wp.showCmd);
  393.     myApp.WriteProfileInt (version, "x1", wp.rcNormalPosition.left);
  394.     myApp.WriteProfileInt (version, "y1", wp.rcNormalPosition.top);
  395.     myApp.WriteProfileInt (version, "x2", wp.rcNormalPosition.right);
  396.     myApp.WriteProfileInt (version, "y2", wp.rcNormalPosition.bottom);
  397. }
  398.  
  399. void CMainWindow::UpdateSystemMenu (CMenu* pMenu)
  400. {
  401.     static UINT nState[2][5] = {
  402.         { MFS_GRAYED,  MFS_ENABLED, MFS_ENABLED,
  403.           MFS_ENABLED, MFS_DEFAULT },
  404.         { MFS_DEFAULT, MFS_GRAYED,  MFS_GRAYED,
  405.           MFS_ENABLED, MFS_GRAYED  }
  406.     };
  407.  
  408.     if (IsIconic ()) // Shouldn't happen, but let's be safe
  409.         return;
  410.  
  411.     int i = 0;
  412.     if (IsZoomed ())
  413.         i = 1;
  414.  
  415.     CString strMenuText;
  416.     pMenu->GetMenuString (SC_RESTORE, strMenuText, MF_BYCOMMAND);
  417.     pMenu->ModifyMenu (SC_RESTORE, MF_STRING | nState[i][0], SC_RESTORE,
  418.         strMenuText);
  419.  
  420.     pMenu->GetMenuString (SC_MOVE, strMenuText, MF_BYCOMMAND);
  421.     pMenu->ModifyMenu (SC_MOVE, MF_STRING | nState[i][1], SC_MOVE,
  422.         strMenuText);
  423.  
  424.     pMenu->GetMenuString (SC_SIZE, strMenuText, MF_BYCOMMAND);
  425.     pMenu->ModifyMenu (SC_SIZE, MF_STRING | nState[i][2], SC_SIZE,
  426.         strMenuText);
  427.  
  428.     pMenu->GetMenuString (SC_MINIMIZE, strMenuText, MF_BYCOMMAND);
  429.     pMenu->ModifyMenu (SC_MINIMIZE, MF_STRING | nState[i][3], SC_MINIMIZE,
  430.         strMenuText);
  431.  
  432.     pMenu->GetMenuString (SC_MAXIMIZE, strMenuText, MF_BYCOMMAND);
  433.     pMenu->ModifyMenu (SC_MAXIMIZE, MF_STRING | nState[i][4], SC_MAXIMIZE,
  434.         strMenuText);
  435.  
  436.     SetMenuDefaultItem (pMenu->m_hMenu, i ? SC_RESTORE :
  437.         SC_MAXIMIZE, FALSE);
  438. }
  439.  
  440. /////////////////////////////////////////////////////////////////////////
  441. // CAboutDialog message map and member functions
  442.  
  443. BEGIN_MESSAGE_MAP (CAboutDialog, CDialog)
  444.     ON_WM_PAINT ()
  445. END_MESSAGE_MAP ()
  446.  
  447. BOOL CAboutDialog::OnInitDialog ()
  448. {
  449.     CDialog::OnInitDialog ();
  450.  
  451.     CStatic* pStatic = (CStatic*) GetDlgItem (IDC_ICONRECT);
  452.     pStatic->GetWindowRect (&m_rect);
  453.     pStatic->DestroyWindow ();
  454.     ScreenToClient (&m_rect);
  455.  
  456.     return TRUE;
  457. }
  458.  
  459. void CAboutDialog::OnPaint ()
  460. {
  461.     CPaintDC dc (this);
  462.     HICON hIcon = (HICON) ::GetClassLong (AfxGetMainWnd ()->m_hWnd,
  463.         GCL_HICON);
  464.  
  465.     if (hIcon != NULL) {
  466.         CDC dcMem;
  467.         dcMem.CreateCompatibleDC (&dc);
  468.  
  469.         CBitmap bitmap;
  470.         bitmap.CreateCompatibleBitmap (&dc, 32, 32);
  471.         CBitmap* pOldBitmap = dcMem.SelectObject (&bitmap);
  472.  
  473.         CBrush brush (::GetSysColor (COLOR_3DFACE));
  474.         dcMem.FillRect (CRect (0, 0, 32, 32), &brush);
  475.         dcMem.DrawIcon (0, 0, hIcon);
  476.  
  477.         dc.StretchBlt (m_rect.left, m_rect.top, m_rect.Width(),
  478.             m_rect.Height (), &dcMem, 0, 0, 32, 32, SRCCOPY);
  479.  
  480.         dcMem.SelectObject (pOldBitmap);
  481.     }
  482. }
  483.